﻿using Microsoft.AspNetCore.Cryptography.KeyDerivation;
using System.Security.Cryptography;
using System.Text;

namespace Infrastructure.Utils
{
    /// <summary>
    ///PBKDF2：Password-Based Key Derivation Function 2
    ///1，口令相同，密文也不同 [固长69位 eg:smXNrTjw/eDOYTzP3QR/0w==.fdQ5/PgIRL4DSJAGZpfFdqXFEx4SPuzYZ0aDugQn/Ic=]
    ///2，标准化
    ///3，即使有加密方法和密文数据，也获取不到口令
    /// </summary>
    public class Password
    {
        /// <summary>
        /// 密码生成
        /// </summary>
        /// <param name="password"></param>
        /// <returns>密码</returns>
        public static string Create(string password)
        {
            var salt = _generateSalt();
            var hash = _hashPassword(password, salt);
            var result = $"{salt}.{hash}";
            return result;
        }
        /// <summary>
        /// 密码验证
        /// </summary>
        /// <param name="password">输入的口令</param>
        /// <param name="storePassword">存储的密码</param>
        /// <returns></returns>
        public static bool Verify(string password, string storePassword)
        {
            if (string.IsNullOrEmpty(password)) throw new ArgumentNullException(nameof(password));
            if (string.IsNullOrEmpty(storePassword)) throw new ArgumentNullException(nameof(storePassword));
            var parts = storePassword.Split('.');
            return _hashPassword(password, parts[0]) == parts[1];
        }
        //通过口令和盐值生成密文
        private static string _hashPassword(string value, string salt)
        {
            var valueBytes = KeyDerivation.Pbkdf2(
                password: value,
                salt: Encoding.UTF8.GetBytes(salt),//盐值，一个随机数
                prf: KeyDerivationPrf.HMACSHA512,//伪随机函数
                iterationCount: 5000,//迭代次数
                numBytesRequested: 256 / 8);//密钥长度
            return Convert.ToBase64String(valueBytes);
        }
        //生产salt盐值随机数
        private static string _generateSalt()
        {
            byte[] randomBytes = new byte[128 / 8];
            using var generator = RandomNumberGenerator.Create();
            generator.GetBytes(randomBytes);
            return Convert.ToBase64String(randomBytes);
        }
    }

    /// <summary>
    /// 生成32位密码（口令相同时密文相同）eg:m5OYCIdyg2KrZLExNB3u9XC07Cljgv0R
    /// </summary>
    [Obsolete]
    public class Password32
    {
        public static string securityKey => HashHelper.MD5_32("*@%&~^");

        #region 生成密码
        /// <summary>
        /// 生成32位密文 无法解密
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string Create(string str)
        {
            var res = DESEncrypt(HashHelper.MD5_32(str).Substring(0, 16), HashHelper.MD5_32(securityKey).Substring(0, 8), HashHelper.MD5_32(securityKey).Substring(1, 8));
            return res;
        }
        #endregion

        #region DES法 加解密
        /// <summary>  
        /// C# DES解密方法  
        /// </summary>  
        /// <param name="encryptedValue">待解密的字符串</param>  
        /// <param name="key">密钥</param>  
        /// <param name="iv">向量</param>  
        /// <returns>解密后的字符串</returns>  
        public static string DESDecrypt(string encryptedValue, string key, string iv)
        {
            using (DESCryptoServiceProvider sa =
                new DESCryptoServiceProvider
                { Key = Encoding.UTF8.GetBytes(key), IV = Encoding.UTF8.GetBytes(iv) })
            {
                using (ICryptoTransform ct = sa.CreateDecryptor())
                {
                    byte[] byt = Convert.FromBase64String(encryptedValue);

                    using (var ms = new MemoryStream())
                    {
                        using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
                        {
                            cs.Write(byt, 0, byt.Length);
                            cs.FlushFinalBlock();
                        }
                        return Encoding.UTF8.GetString(ms.ToArray());
                    }
                }
            }
        }
        /// <summary>  
        /// C# DES加密方法  
        /// </summary>  
        /// <param name="encryptedValue">要加密的字符串</param>  
        /// <param name="key">密钥</param>  
        /// <param name="iv">向量</param>  
        /// <returns>加密后的字符串</returns>  
        public static string DESEncrypt(string originalValue, string key, string iv)
        {
            using (DESCryptoServiceProvider sa
                = new DESCryptoServiceProvider { Key = Encoding.UTF8.GetBytes(key), IV = Encoding.UTF8.GetBytes(iv) })
            {
                using (ICryptoTransform ct = sa.CreateEncryptor())
                {
                    byte[] by = Encoding.UTF8.GetBytes(originalValue);
                    using (var ms = new MemoryStream())
                    {
                        using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
                        {
                            cs.Write(by, 0, by.Length);
                            cs.FlushFinalBlock();
                        }
                        return Convert.ToBase64String(ms.ToArray());
                    }
                }
            }
        }
        #endregion

    }
}
